package com.app.common.utils.http;

import okhttp3.*;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class HttpRequest {

    private static final OkHttpClient CLIENT = new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .build();

    private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");

    /** -------------------- GET 请求 -------------------- **/
    public static String get(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (params != null) {
            params.forEach(urlBuilder::addQueryParameter);
        }
        Request.Builder builder = new Request.Builder().url(urlBuilder.build()).get();

        // 添加自定义头
        addHeaders(builder, headers);

        return execute(builder.build());
    }

    /** -------------------- POST JSON -------------------- **/
    public static String postJson(String url, String json, Map<String, String> headers) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request.Builder builder = new Request.Builder()
                .url(url)
                .post(body);

        addHeaders(builder, headers);

        return execute(builder.build());
    }

    /** -------------------- POST 表单 -------------------- **/
    public static String postForm(String url, Map<String, String> formParams, Map<String, String> headers) throws IOException {
        FormBody.Builder formBuilder = new FormBody.Builder();
        if (formParams != null) {
            formParams.forEach(formBuilder::add);
        }

        Request.Builder builder = new Request.Builder()
                .url(url)
                .post(formBuilder.build());

        addHeaders(builder, headers);

        return execute(builder.build());
    }

    /** -------------------- PUT JSON -------------------- **/
    public static String putJson(String url, String json, Map<String, String> headers) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request.Builder builder = new Request.Builder()
                .url(url)
                .put(body);

        addHeaders(builder, headers);

        return execute(builder.build());
    }

    /** -------------------- DELETE -------------------- **/
    public static String delete(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (params != null) {
            params.forEach(urlBuilder::addQueryParameter);
        }

        Request.Builder builder = new Request.Builder()
                .url(urlBuilder.build())
                .delete();

        addHeaders(builder, headers);

        return execute(builder.build());
    }

    /** -------------------- 上传文件 -------------------- **/
    public static String uploadFile(String url, File file, Map<String, String> formParams, Map<String, String> headers) throws IOException {
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

        if (formParams != null) {
            formParams.forEach(builder::addFormDataPart);
        }

        builder.addFormDataPart("file", file.getName(),
                RequestBody.create(MediaType.parse("application/octet-stream"), file));

        Request.Builder reqBuilder = new Request.Builder()
                .url(url)
                .post(builder.build());

        addHeaders(reqBuilder, headers);

        return execute(reqBuilder.build());
    }

    /** -------------------- 下载文件 -------------------- **/
    public static String downloadFile(String url, String savePath, Map<String, String> headers) throws IOException {
        Request.Builder builder = new Request.Builder()
                .url(url)
                .get();

        addHeaders(builder, headers);

        try (Response response = CLIENT.newCall(builder.build()).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("下载失败: " + response);
            }

            File target = new File(savePath);
            Files.createDirectories(target.getParentFile().toPath());

            try (InputStream in = response.body().byteStream();
                 FileOutputStream out = new FileOutputStream(target)) {
                byte[] buf = new byte[8192];
                int len;
                while ((len = in.read(buf)) != -1) {
                    out.write(buf, 0, len);
                }
            }
        }

        return savePath;
    }

    /** -------------------- 公共执行 -------------------- **/
    private static String execute(Request request) throws IOException {
        try (Response response = CLIENT.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("请求失败: " + response);
            }
            return response.body().string();
        }
    }

    /** -------------------- 添加头部 -------------------- **/
    private static void addHeaders(Request.Builder builder, Map<String, String> headers) {
        if (headers != null && !headers.isEmpty()) {
            headers.forEach(builder::addHeader);
        }
    }
}
